package com.cloud.picture.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloud.picture.common.BaseResponse;
import com.cloud.picture.constant.UserConstants;
import com.cloud.picture.exception.BusinessException;
import com.cloud.picture.mapper.MessageMapper;
import com.cloud.picture.mapper.UserFollowMapper;
import com.cloud.picture.mapper.UserMapper;
import com.cloud.picture.model.dto.DeleteRequest;
import com.cloud.picture.model.dto.user.UserAddRequest;
import com.cloud.picture.model.dto.user.UserFollowRequest;
import com.cloud.picture.model.dto.user.UserInfoUpdateRequest;
import com.cloud.picture.model.dto.user.UserQueryRequest;
import com.cloud.picture.model.dto.user.message.MessageAddRequest;
import com.cloud.picture.model.dto.user.message.MessageListRequest;
import com.cloud.picture.model.entity.Message;
import com.cloud.picture.model.entity.User;
import com.cloud.picture.model.entity.UserFollow;
import com.cloud.picture.model.enums.ErrorCodeEnum;
import com.cloud.picture.model.enums.UserRoleEnum;
import com.cloud.picture.model.vo.FollowerVO;
import com.cloud.picture.model.vo.LoginUserVO;
import com.cloud.picture.model.vo.MessageVO;
import com.cloud.picture.model.vo.UserVO;
import com.cloud.picture.service.UserService;
import com.cloud.picture.utils.ResultUtils;
import com.cloud.picture.utils.ThrowUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.cloud.picture.constant.UserConstants.*;

/**
* @author win
* @description 针对表【user(用户)】的数据库操作Service实现
* @createDate 2025-03-01 10:37:39
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService{

    @Resource
    private JavaMailSender mailSender;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private UserFollowMapper userFollowMapper;

    @Resource
    private MessageMapper messageMapper;

    @Override
    public BaseResponse<Boolean> sendVerificationCode(String email) {
        // 1. 参数校验
        ThrowUtils.throwIf(email == null || email.isEmpty(), ErrorCodeEnum.PARAMS_ERROR, "邮箱不能为空");
        ThrowUtils.throwIf(!email.matches("^[a-zA-Z0-9_-]+@qq\\.com$"), ErrorCodeEnum.PARAMS_ERROR, "仅支持QQ邮箱");

        // 2. 生成6位随机验证码
        // @Todo 原生Random使用低效问题
        String verificationCode = String.format("%06d", new Random().nextInt(999999));
        
        // 3. 构建邮件内容
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom("3025243841@qq.com"); 
        message.setTo(email);
        message.setSubject("云图网验证码");
        message.setText("尊敬的用户：\n\n您好！\n\n您的验证码是：" + verificationCode + 
                      "\n\n该验证码5分钟内有效，请勿泄露给他人。\n\n如非本人操作，请忽略此邮件。\n\n云图网团队");
        
        try {
            // 4. 发送邮件
            mailSender.send(message);
            
            // 5. 将验证码存入Redis,设置5分钟过期
            redisTemplate.opsForValue().set(EMAIL_CODE_KEY + email, verificationCode, 5 , TimeUnit.MINUTES);

            return ResultUtils.success(true);
        } catch (Exception e) {
            log.error("发送验证码失败, email={}, error={}", email, e.getMessage());
            throw new BusinessException(ErrorCodeEnum.SYSTEM_ERROR, "验证码发送失败,请稍后重试");
        }
    }

    @Override
    public Boolean verifyCode(String email, String code) {
        ThrowUtils.throwIf(email == null || email.isEmpty(), ErrorCodeEnum.PARAMS_ERROR, "参数为空");
        redisTemplate.opsForValue().get(EMAIL_CODE_KEY + email);
        return code.equals(redisTemplate.opsForValue().get(EMAIL_CODE_KEY + email));
    }

    @Override
    public long userRegister(String userAccount, String userEmail, String userPassword, String checkPassword, String code) {
        // 1. 校验
        ThrowUtils.throwIf(StringUtils.isAllBlank(userAccount,userEmail, userPassword,checkPassword,code), ErrorCodeEnum.PARAMS_ERROR);
        ThrowUtils.throwIf(userAccount.length() < 4, ErrorCodeEnum.PARAMS_ERROR, "用户名过短");
        ThrowUtils.throwIf(userPassword.length() < 6, ErrorCodeEnum.PARAMS_ERROR, "密码过短");
        ThrowUtils.throwIf(!userPassword.equals(checkPassword), ErrorCodeEnum.PARAMS_ERROR, "两次输入的密码不一致");
        // @Todo 未知警告由锁的不完全正确使用导致
        synchronized (userEmail.intern()){
            // 2. 检查是否重复
//            // 检查邮箱
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//            queryWrapper.eq("user_email", userEmail);
//            long count = this.baseMapper.selectCount(queryWrapper);
//            ThrowUtils.throwIf(count > 0, ErrorCodeEnum.PARAMS_ERROR, "该邮箱已注册");
            // 检查账号
            queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_account", userAccount);
            long count = this.baseMapper.selectCount(queryWrapper);
            ThrowUtils.throwIf(count > 0, ErrorCodeEnum.PARAMS_ERROR, "账号重复");

            // 3. 加密
            String encryptPassword = getEncryptPassword(userPassword);

            // 4. 插入数据
            User user = User.builder()
                    .userAccount(userAccount)
                    .userPassword(encryptPassword)
                    // 账号为默认昵称
                    .userName(userAccount)
                    .userEmail(userEmail)
                    .userRole(UserRoleEnum.USER.getValue())
                    .build();
            boolean save = this.save(user);
            ThrowUtils.throwIf(!save, ErrorCodeEnum.SYSTEM_ERROR, "注册失败，数据库错误");
            // 删除验证码
            redisTemplate.delete(EMAIL_CODE_KEY + userEmail);
            // 5. 返回结果
            return user.getId();
        }
    }

    @Override
    public String getEncryptPassword(String password) {
        return DigestUtils.md5DigestAsHex((UserConstants.SALT + password).getBytes());
    }

    @Override
    public LoginUserVO userLogin(String userAccount, String userPassword, HttpServletRequest request) {
        // 1.校验
        ThrowUtils.throwIf(CharSequenceUtil.hasBlank(userAccount, userPassword), ErrorCodeEnum.PARAMS_ERROR, "参数为空");
        ThrowUtils.throwIf(userAccount.length() < 4, ErrorCodeEnum.PARAMS_ERROR, "用户名过短");
        ThrowUtils.throwIf(userPassword.length() < 6, ErrorCodeEnum.PARAMS_ERROR, "密码过短");
        // 2.加密
        String encryptPassword = getEncryptPassword(userPassword);
        // 3.查询用户是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_account", userAccount);
        queryWrapper.eq("user_password", encryptPassword);
        User user = this.baseMapper.selectOne(queryWrapper);
        ThrowUtils.throwIf(user == null, ErrorCodeEnum.PARAMS_ERROR, "账号密码不匹配");
        // 4.记录用户登录态
        request.getSession().setAttribute(USER_LOGIN_STATE, user);
        // 5.返回结果
        return this.getLoginUserVO(user);
    }

    @Override
    public LoginUserVO getLoginUserVO(User user) {
        if (user == null) {
            return null;
        }
        LoginUserVO loginUserVO = new LoginUserVO();
        BeanUtils.copyProperties(user, loginUserVO);
        return loginUserVO;
    }

    @Override
    public User getLoginUser(HttpServletRequest request) {
        // 1. 判断是否登录
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        User currentUser = (User)userObj;
        if(currentUser == null || currentUser.getId() == null) {
            return null;
        }
        // 2. 获取用户信息
        long userId = currentUser.getId();
        currentUser = this.getById(userId);
        ThrowUtils.throwIf(currentUser == null, ErrorCodeEnum.NOT_LOGIN_ERROR);
        // 3. 返回用户信息
        return currentUser;
    }

    @Override
    public Boolean userLogout(HttpServletRequest request) {
        // 1. 判断是否登录
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        ThrowUtils.throwIf(userObj == null, ErrorCodeEnum.NOT_LOGIN_ERROR);
        // 2. 清除用户登录态
        request.getSession().removeAttribute(USER_LOGIN_STATE);
        // 3. 返回结果
        return true;
    }

    @Override
    public UserVO getUserVO(User user) {
        // 1. 校验
        if (user == null) {
            return null;
        }
        // 2. 转换
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }

    @Override
    public List<UserVO> getUserVOList(List<User> userList) {
        // 1. 校验
        if (CollUtil.isEmpty(userList)) {
            return new ArrayList<>();
        }
        // 2. 转换
        return userList.stream().map(this::getUserVO).collect(Collectors.toList());
    }

    @Override
    public QueryWrapper<User> getQueryWrapper(UserQueryRequest userQueryRequest) {
        // 1. 校验
        ThrowUtils.throwIf(userQueryRequest == null, ErrorCodeEnum.PARAMS_ERROR, "请求参数为空");
        // 2. 拼接查询条件
        Long id = userQueryRequest.getId();
        String userName = userQueryRequest.getUserName();
        String userAccount = userQueryRequest.getUserAccount();
        String userProfile = userQueryRequest.getUserProfile();
        String userRole = userQueryRequest.getUserRole();
        String userEmail = userQueryRequest.getUserEmail();
        String userPhone = userQueryRequest.getUserPhone();
        String sortField = userQueryRequest.getSortField();
        String sortOrder = userQueryRequest.getSortOrder();
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ObjectUtil.isNotNull(id),"id", id);
        queryWrapper.eq(CharSequenceUtil.isNotBlank(userEmail), "user_email", userEmail);
        queryWrapper.eq(CharSequenceUtil.isNotBlank(userPhone), "user_phone", userPhone);
        queryWrapper.eq(CharSequenceUtil.isNotBlank(userRole), "user_role", userRole);
        queryWrapper.like(CharSequenceUtil.isNotBlank(userName), "user_name", userName);
        queryWrapper.like(CharSequenceUtil.isNotBlank(userAccount), "user_account", userAccount);
        queryWrapper.like(CharSequenceUtil.isNotBlank(userProfile), "user_profile", userProfile);
        queryWrapper.orderBy(CharSequenceUtil.isNotBlank(sortField), "ascend".equals(sortOrder), sortField);
        return queryWrapper;
    }

    @Override
    public Boolean userInfoUpdate(UserInfoUpdateRequest userInfoUpdateRequest) {
        // 1. 校验
        ThrowUtils.throwIf(userInfoUpdateRequest.getId() == null, ErrorCodeEnum.OPERATION_ERROR);
        // 2. 更新
        User user = User.builder().build();
        BeanUtils.copyProperties(userInfoUpdateRequest, user);
        return this.baseMapper.updateById(user) > 0;
    }

    @Override
    public long addUser(UserAddRequest userAddRequest) {
        // 1. 校验
        ThrowUtils.throwIf(userAddRequest == null, ErrorCodeEnum.PARAMS_ERROR);
        // 2. 插入数据
        User user = User.builder().build();
        BeanUtils.copyProperties(userAddRequest, user);
        String encryptPassword = this.getEncryptPassword(USER_DEFAULT_PASSWORD);
        user.setUserPassword(encryptPassword);
        // 3. 返回结果
        return this.baseMapper.insert(user);
    }

    @Override
    public User getUserById(long id) {
        // 1. 查询
        User user = this.baseMapper.selectById(id);
        // 2. 返回结果
        return user;
    }

    @Override
    public UserVO getUserVoById(long id) {
        // 1. 查询
        User user = this.getUserById(id);
        // 2. 脱敏
        UserVO userVO = this.getUserVO(user);
        // 3. 返回结果
        return userVO;
    }

    @Override
    public boolean deleteUser(DeleteRequest deleteRequest) {
        return this.baseMapper.deleteById(deleteRequest.getId()) > 0;
    }

    @Override
    public boolean isAdmin(User user) {
        return user != null && UserRoleEnum.ADMIN.getValue().equals(user.getUserRole());
    }

    @Override
    public Boolean userFollow(UserFollowRequest followRequest) {
        // 1. 校验
        ThrowUtils.throwIf(followRequest.getFollowerId() == null || followRequest.getUserId() == null, ErrorCodeEnum.PARAMS_ERROR);

        QueryWrapper<UserFollow> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", followRequest.getUserId());
        queryWrapper.eq("follower_id", followRequest.getFollowerId());

        UserFollow existingUserFollow = userFollowMapper.selectOne(queryWrapper);

        if (existingUserFollow != null) {
            userFollowMapper.delete(queryWrapper);
        } else {
            UserFollow userFollow = new UserFollow();
            userFollow.setUserId(followRequest.getUserId());
            userFollow.setFollowerId(followRequest.getFollowerId());
            userFollowMapper.insert(userFollow);
        }
        return true;
    }

    @Override
    public Boolean sendMessage(MessageAddRequest messageAddRequest) {
        // 1. 校验
        ThrowUtils.throwIf(messageAddRequest.getSenderId() == null || messageAddRequest.getReceiverId() == null, ErrorCodeEnum.PARAMS_ERROR);
        // 2. 插入数据
        Message message = new Message();
        message.setToUserId(messageAddRequest.getReceiverId());
        message.setFromUserId(messageAddRequest.getSenderId());
        message.setMessageContent(messageAddRequest.getContent());
        int res = this.messageMapper.insert(message);
        ThrowUtils.throwIf(res <= 0, ErrorCodeEnum.OPERATION_ERROR);
        // 3. 返回结果
        return true;
    }

    @Override
    public Page<MessageVO> getMessageByPage(MessageListRequest messageListRequest) {
        // 1. 校验
        ThrowUtils.throwIf(messageListRequest.getReviewerId() == null, ErrorCodeEnum.PARAMS_ERROR);
        // 2. 封装分页

        // 3. 分页查询
        // 4. 返回结果
        return null;
    }

    @Override
    public Page<FollowerVO> getFollowerByPage(UserFollowRequest userFollowRequest) {
        // 1. 校验
        // 2. 封装分页
        // 3. 分页查询
        // 4. 返回结果
        return null;
    }

    @Override
    public Page<FollowerVO> getFollowingByPage(UserFollowRequest userFollowRequest) {
        // 1. 校验
        // 2. 封装分页
        // 3. 分页查询
        // 4. 返回结果
        return null;
    }

    @Override
    public String sendEmail(String email) {
        String code = "发送成功";
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom("3025243841@qq.com");
        message.setTo(email);
        message.setSubject("测试邮件");
        message.setText("测试邮件内容");
        mailSender.send(message);
        return code;
    }
}




